package com.eg366.proxy.jdk;

import java.io.FileOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import sun.misc.ProxyGenerator;

import com.eg366.proxy.service.IBehavior;
import com.eg366.proxy.service.impl.DefaultBehavior;

public class JdkProxyClient {

	public static void main(String[] args) throws Exception {
		defaultStyle();
		stepStyle();
		createProxyClassFile();
	}

	/**
	 * jdk默认方式实现动态代理
	 */
	private static void defaultStyle() {
		IBehavior target = new DefaultBehavior();
		InvocationHandlerTest ihTest = new InvocationHandlerTest(target);

		IBehavior proxy = (IBehavior) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass()
				.getInterfaces(), ihTest);
		proxy.eat();

		createProxyClassFile();
	}

	/**
	 * 分步骤实现动态代理
	 */
	private static void stepStyle() throws Exception {
		InvocationHandlerTest ihTest = new InvocationHandlerTest(new DefaultBehavior());
		
		/* 以下步骤为Proxy.newProxyInstance方式的简化 */
		/* （1）创建代理对象Class； extends Proxy implments IBehavior */
		Class clazz = Proxy.getProxyClass(ihTest.getClass().getClassLoader(), IBehavior.class);
//		clazz.getMethod("eat");
		/* （2）由于继承自Proxy，获得父类Proxy的构造方法；Proxy(InvocationHandler h) */
		Constructor constructor = clazz.getConstructor(InvocationHandler.class);
		/* （3）调用InvocationHandler参数构造方法，传入参数，创建代理对象 */
		IBehavior proxy = (IBehavior) constructor.newInstance(ihTest);
		
		/* 会调用InvocationHandler的invoke方法 */
		proxy.eat();
	}

	/**
	 * 创建proxy对象class文件
	 */
	private static void createProxyClassFile() {
		String name = "ProxySubject";
		byte[] data = ProxyGenerator.generateProxyClass(name, new Class[] { IBehavior.class });
		try {
			FileOutputStream out = new FileOutputStream(name + ".class");
			out.write(data);
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
